﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MadMilkman.Ini;
using MdcService.Static;
using MdcService.Structure.Enum;

namespace MdcService.Configuration
{
    public class IniMachinesManager:IConfigurationManager<IList<MachineDefinition>>
    {

        private const string CryptString = null; //"(ง •̀_•́)ง";
        private readonly IniOptions _iniOptions = new IniOptions
        {
            Encoding = Encoding.UTF8,
            EncryptionPassword = CryptString
        };

        public string MachineDefinitionPath = @".\\Machines";
        public string MachineDefinitionExt = @"txt";

        public IList<MachineDefinition> Load()
        {
            var ls = new List<MachineDefinition>();
            var ds = new DirectoryInfo(this.MachineDefinitionPath);
            ds.EnumerateFiles($"*.{this.MachineDefinitionExt}").ForEach(i =>
            {
                IniFile ini = new IniFile(_iniOptions);
                ini.Load(i.FullName);
                if (ini.Sections.Contains("Control") && ini.Sections.Contains("Tags") && ini.Sections["Control"].Keys.Contains("Id")
                    && ini.Sections["Control"].Keys.Contains("Name") && ini.Sections["Control"].Keys.Contains("Type") &&
                    ini.Sections["Control"].Keys.Contains("Path") && ini.Sections["Control"].Keys.Contains("Enabled"))
                {
                    var n = new MachineDefinition
                    {
                        Id = Path.GetFileNameWithoutExtension(i.Name),
                        Name = ini.Sections["Control"].Keys["Name"].Value,
                        Type = (MachineType)Convert.ToInt32(ini.Sections["Control"].Keys["Type"].Value),
                        Path = ini.Sections["Control"].Keys["Path"].Value,
                        Enabled = Convert.ToBoolean(ini.Sections["Control"].Keys["Enabled"].Value),
                        Tags = ini.Sections["Tags"].Keys.ToDictionary(j => j.Name, j => j.Value)
                    };
                    ls.Add(n);
                }
                else
                {
                    File.Delete(i.FullName);
                }

            });

            return ls;
        }

        public void Save(MachineDefinition machineDefinition)
        {
            string s = $"{this.MachineDefinitionPath}\\{machineDefinition.Id}.{this.MachineDefinitionExt}";
            if (!Directory.Exists(MachineDefinitionPath))
            {
                Directory.CreateDirectory(MachineDefinitionPath);
            }
            if (!File.Exists(s))
            {
                using (var f = File.Create(s))
                {
                    f.Close();
                }
                var ini = new IniFile(_iniOptions);
                ini.Sections.Add("Control");
                ini.Sections["Control"].Keys.Add("Id", machineDefinition.Id);
                ini.Sections["Control"].Keys.Add("Name", machineDefinition.Name);
                ini.Sections["Control"].Keys.Add("Type", ((int) machineDefinition.Type).ToString());
                ini.Sections["Control"].Keys.Add("Path", machineDefinition.Path);
                ini.Sections["Control"].Keys.Add("Enabled", machineDefinition.Enabled.ToString());
                ini.Sections.Add("Tags");
                machineDefinition.Tags.ForEach(i =>
                {
                    ini.Sections["Tags"].Keys.Add(i.Key, i.Value);
                });
                ini.Save(s);
            }
            else
            {
                machineDefinition.Id = Utilities.NewId();
                Save(machineDefinition);
            }
        }

        public void Save(IList<MachineDefinition> machineDefinitions)
        {
            var ds = new DirectoryInfo(this.MachineDefinitionPath);
            var ids = machineDefinitions.Select(j => j.Id);
            ds.EnumerateFiles($"*.{this.MachineDefinitionExt}").ForEach(i =>
            {
                if (!ids.Contains(i.Name))
                {
                    File.Delete(i.FullName);
                }
            });
            machineDefinitions.ForEach(Save);
        }

        public void Delete(MachineDefinition machineDefinition)
        {
            string s = $"{machineDefinition.Id}.{this.MachineDefinitionExt}";
            if (File.Exists(s)) File.Delete(s);
        }
    }
}
